package com.pig4cloud.pigx.common.customize.mysql.mybatis.interceptor;

import com.pig4cloud.pigx.common.customize.security.utils.SecurityUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

/**
 * mybatis新增/修改时，初始化创建人、修改人相关数据
 *
 * @return {@link }
 * @date 2022/8/14 16:20
 */
@Slf4j
@Component
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
@AllArgsConstructor
public class MybatisInitInstanceInterceptor implements Interceptor {

	private final SecurityUtil securityUtil;

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
		log.debug("------sqlId------" + mappedStatement.getId());

		// sql类型：insert、update、select、delete
		SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
		Object parameter = invocation.getArgs()[1];
		log.debug("------sqlCommandType------" + sqlCommandType);

		if (parameter == null) {
			return invocation.proceed();
		}

		// 如果是不是新增/修改操作，直接结束
		if (SqlCommandType.INSERT != sqlCommandType && SqlCommandType.UPDATE != sqlCommandType) {
			return invocation.proceed();
		}


		// 当sql为新增或更新类型时，自动填充操作人相关信息
		if (SqlCommandType.INSERT == sqlCommandType) {
			securityUtil.initCreateAbout(parameter);

		} else if (SqlCommandType.UPDATE == sqlCommandType) {
			securityUtil.initUpdateAbout(parameter);
		}

		return invocation.proceed();
	}

	/**
	 * 将当前拦截器（插件）生成代理存到拦截器链中（InterceptorChain）
	 *
	 * @param target target
	 * @return {@link Object}
	 * @date 2022/8/14 16:18
	 */
	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	/**
	 * 读取注册插时传入的相关参数
	 *
	 * @param properties 参数
	 * @date 2022/8/14 16:18
	 */
	@Override
	public void setProperties(Properties properties) {
		// TODO Auto-generated method stub
	}

	/**
	 * 获取类的所有属性，包括父类
	 *
	 * @param object
	 * @return
	 */
	private Field[] getAllFields(Object object) {
		Class<?> clazz = object.getClass();
		List<Field> fieldList = new ArrayList<>();
		while (clazz != null) {
			fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
			clazz = clazz.getSuperclass();
		}
		Field[] fields = new Field[fieldList.size()];
		fieldList.toArray(fields);
		return fields;
	}

}
